[小ネタ] WSL環境からVisual Studio Codeのリモート起動を行う際のひと工夫

[小ネタ] WSL環境からVisual Studio Codeのリモート起動を行う際のひと工夫

Clock Icon2024.11.04

しばたです。

Visual Studio Code(以後VS Code)をインストール済みのWindows環境において、デフォルト設定であればWSL内部からcodeコマンドを実行するとリモート開発の設定がよしなに行われWSL内部のファイルを容易に編集できます。

a-little-trick-to-start-vs-code-remote-in-wsl-01
WSL内部から code コマンドを実行するとホスト側で編集できる

これはWSLのデフォルトでWindowsホスト側のPATH環境変数が共有されており、WSL内部からホスト側のVS Codeバイナリ(codeコマンド)を呼び出せるため実現可能となっています。

ただ、WSLではPATH環境変数を共有しない設定も可能であり、この場合はホスト側のcodeコマンドを呼び出せないためエラーになってしまいます。

/etc/wsl.conf
# PATH環境変数の共有をしない設定
[interop]
appendWindowsPath = false

/etc/wsl.confの設定内容次第でcodeコマンドの起動に失敗しVS Codeを開くことができません。

a-little-trick-to-start-vs-code-remote-in-wsl-02
ホスト側の code コマンドを呼び出せないためエラーになる

本記事ではこの様な「PATH環境変数を共有しない」環境での代替策とちょっとした工夫について解説します。

前提条件

以降の内容は次の前提条件で動作検証しています。

  • Windows 11 Pro (23H2) 環境
  • User Installで最新のVS Codeをインストール済み + Remote Development拡張インストール済み
  • WSL2にUbuntuをインストールして初期設定済み
  • ログインシェルはデフォルトのBashのまま
  • wsl.conf の設定で環境変数の共有をしない様にしている

対策1. WSL内部のPATH環境変数を自分で設定する

「すべてのPATHが共有されるのは困るが、VS CodeのPATHだけなら共有しても良い」のであれば、WSL内部設定でVS CodeのPATHを追加するのが手っ取り早いでしょう。

たとえばWindowsホスト側のVS Codeが

  • C:\Users\shibata\AppData\Local\Programs\Microsoft VS Code\bin

にインストールされている場合[1]、WSL内部から見ると

  • /mnt/c/Users/shibata/AppData/Local/Programs/Microsoft VS Code/bin

というパスになります。

このため、例えばBashを使っている場合は~/.profile~/.bashrc

~/.porfile等
# VS Code用のPATHを追加
export PATH=$PATH:'/mnt/c/Users/shibata/AppData/Local/Programs/Microsoft VS Code/bin'

といった感じでPATHを追加してやればエラーを解消できます。

ひと工夫してみる

これはこれで問題無いのですが、/c/Users/shibata/の部分でユーザー名が決め打ちになっており、個人的にはもう少し汎用的な記述にしたいところです。

汎用的にするためにはプログラム的にユーザー情報を取得する必要がありますが、WSL内部からWindowsホスト側のユーザー情報を直接取得する手段が無いため、ホスト側のプログラムを実行した結果を取り込む形で実現することにしました。

取得する情報に応じて実行内容は変わりますが、今回はホスト側のUSERPROFILE環境変数の値を取得することにしました。
コマンドプロンプトから環境変数を得るのが一番手っ取り早そうだったのでWSL内部から次のコマンドを実行してやります。

WSL内部のBash
# WSLからコマンドプロンプトを起動し、ホスト側の USERPROFILE 環境変数を取得
/mnt/c/WINDOWS/system32/cmd.exe /c 'SET /P X=%USERPROFILE%<NUL' 2>/dev/null

ちょっと変わった記述になっていますが、コマンドプロンプトでは末尾に改行を出力しないecho -nに相当するコマンドが無いためSET /Pを代替に使っています。

加えてコマンドプロンプト起動時にカレントディレクトリに関する警告が出るので2>/dev/nullしています。

実行結果は以下となり期待通りに情報が取れています。

WSL内部のBash
$ /mnt/c/WINDOWS/system32/cmd.exe /c 'SET /P X=%USERPROFILE%<NUL' 2>/dev/null
C:\Users\shibata

ただ、これだとパスの表記がWindowsの記法なのでwslpathコマンドを使ってLinuxの記法に変換してやります。

WSL内部のBash
# wslpathコマンドでパスの形式を変換
wslpath $(/mnt/c/WINDOWS/system32/cmd.exe /c 'SET /P X=%USERPROFILE%<NUL' 2>/dev/null)

結果はこんな感じでLinuxのパス表記に変換されます。

WSL内部のBash
# C:\Users\shibata → /mnt/c/Users/shibata に変換される
$ wslpath $(/mnt/c/WINDOWS/system32/cmd.exe /c 'SET /P X=%USERPROFILE%<NUL' 2>/dev/null)
/mnt/c/Users/shibata

最終的に以下の形でPATHを追加してやれば完成です。

~/.porfile等
# より汎用的な形でPATHを追加
export PATH=$PATH:"$(wslpath $(/mnt/c/WINDOWS/system32/cmd.exe /c 'SET /P X=%USERPROFILE%<NUL' 2>/dev/null))/AppData/Local/Programs/Microsoft VS Code/bin"

これで期待通りWindowsホスト側のVS Codeに対してだけPATHを追加できました。

WSL内部のBash
# 環境変数を確認
$ printenv PATH | tr ':' '\n'
/usr/local/sbin
/usr/local/bin
/usr/sbin
/usr/bin
/sbin
/bin
/usr/games
/usr/local/games
/usr/lib/wsl/lib
/snap/bin
/mnt/c/Users/shibata/AppData/Local/Programs/Microsoft VS Code/bin

余談 : 他シェルの場合

Bash以外のシェルの場合はそのシェルに応じた記述に変えてやる必要があります。
たとえば私が常用しているNushellだと次の記述をconfig.nuに追加する形になります。

Nushell - config.nu
# Nushell on WSLでの設定例
let host_user_profile = wslpath (/mnt/c/WINDOWS/system32/cmd.exe /q /c 'SET /P X=%USERPROFILE%<NUL' | complete | get stdout)
$env.PATH = ($env.PATH | append $"($host_user_profile)/AppData/Local/Programs/Microsoft VS Code/bin")

対策2. ホスト側からVS Code Remoteを実行する

WSL側のPATHを一切変更したくない場合やWSLからWindowsホストのプログラムを実行できない場合はホスト側からcodeコマンドを実行する形でも代替可能です。

上記ドキュメントによればcodeコマンドの--remoteパラメーターでWSL内部のファイルを開けます。

code --remote wsl+<distro name> <path in WSL>

WSLのディストリビューション名はwsl --listコマンドから取得できます。
実行結果は下図の様になり、期待通りの動作をしてくれます。

WindowsホストのPowerShell
# ディストリビューション名が Ubuntu-22.04 の場合の実行例
PS C:\> code --remote wsl+Ubuntu-22.04 /home/username/test

a-little-trick-to-start-vs-code-remote-in-wsl-03

最後に

以上となります。

本記事にある事象と対策自体は既出のものですが、PATHの書き方をもう少しなんとかしたいと思い頑張ってみました。

脚注
  1. User Installerでインストールした場合のパスです ↩︎

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.